package com.yl.common.config.thread;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:
 * @author: liangjian
 */
@EnableScheduling
@Configuration
public class SchedulingConfig {


    /**
     * 如果获取不到cpu核心数，默认为8核
     */
    private static final int CORE = Runtime.getRuntime().availableProcessors() <= 0 ? 8 : Runtime.getRuntime().availableProcessors();


    @Bean("taskScheduler")
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler threadPoolScheduler = new ThreadPoolTaskScheduler();
        threadPoolScheduler.setThreadNamePrefix("SockJS-");
        threadPoolScheduler.setPoolSize(CORE);
        threadPoolScheduler.setRemoveOnCancelPolicy(true);
        return threadPoolScheduler;
    }

    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        //IO 密集型
        int corePoolSize = CORE + 1;
        /**
         * （1+线程等待时间/线程CPU时间 ）* CPU占有率(0 < CPU占有率 <=1) * CPU核心数
         *  预计每个线程在500ms cpu耗时在10ms 占有率60% 大概为 30 * CORE
         */
        int maximumPoolSize = 30 * CORE;
        ThreadPoolTaskExecutor threadPoolScheduler = new ThreadPoolTaskExecutor();
        threadPoolScheduler.setThreadNamePrefix("wssl-thread-pool-");
        threadPoolScheduler.setCorePoolSize(corePoolSize);
        threadPoolScheduler.setMaxPoolSize(maximumPoolSize);
        threadPoolScheduler.setQueueCapacity(100000);
        threadPoolScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolScheduler;
    }

    @Bean("wsslExecutor")
    public ExecutorService wsslExecutor() {
        /*
        线程池参数解析
            https://zhuanlan.zhihu.com/p/341935713
        线程池的线程数 设置参考
            https://blog.csdn.net/zhuimeng_by/article/details/107891268
         */
        //这个线程池主要用于计算 所以是CPU密集型
        //1 核心线程池大小
        int corePoolSize = CORE + 1;
        //2 最大线程池大小
        int maximumPoolSize = CORE * 2;
        //3 空闲线程的存活时间
        long keepAliveTime = 60;
        //4 空闲线程的存活时间 时间单位
        TimeUnit unit = TimeUnit.SECONDS;
        //5 线程等待队列
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10000);
        //6 线程工厂，用来创建新线程
        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger mThreadNum = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "wssl-executor-pool-" + mThreadNum.getAndIncrement());
            }
        };
        //7 拒绝策略
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
                workQueue, threadFactory, handler);
    }

}
